package com.zanfeng.signleplatform.provider.modules.auth;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zanfeng.signleplatform.api.exception.AppRuntimeException;
import com.zanfeng.signleplatform.api.io.modules.auth.AccountDetailIO;
import com.zanfeng.signleplatform.api.io.modules.auth.ModuleDetailIO;
import com.zanfeng.signleplatform.api.io.modules.auth.PermissionDetailIO;
import com.zanfeng.signleplatform.api.io.modules.auth.RoleDetailIO;
import com.zanfeng.signleplatform.api.result.modules.account.AccountResult;
import com.zanfeng.signleplatform.api.result.modules.auth.AuthInfoResult;
import com.zanfeng.signleplatform.api.result.modules.auth.AuthLoginResult;
import com.zanfeng.signleplatform.api.result.modules.auth.RoleModulePermissionResult;
import com.zanfeng.signleplatform.api.result.modules.module.ModuleResult;
import com.zanfeng.signleplatform.api.result.modules.permission.PermissionResult;
import com.zanfeng.signleplatform.api.result.modules.role.RoleResult;
import com.zanfeng.signleplatform.api.service.modules.auth.AuthService;
import com.zanfeng.signleplatform.base.BaseMapper;
import com.zanfeng.signleplatform.common.auth.ApiTokenResult;
import com.zanfeng.signleplatform.common.utils.BeanUtil;
import com.zanfeng.signleplatform.common.utils.CoreUtil;
import com.zanfeng.signleplatform.common.utils.PasswordUtil;
import com.zanfeng.signleplatform.constants.Constants;
import com.zanfeng.signleplatform.dao.persistence.dao.*;
import com.zanfeng.signleplatform.dao.persistence.entity.*;
import com.zanfeng.signleplatform.io.PageListIO;
import com.zanfeng.signleplatform.provider.utils.TokenUtil;
import com.zanfeng.signleplatform.results.FormListResult;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Transactional
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private ModuleMapper moduleMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private TokenUtil tokenUtil;

    @Override
    public AuthLoginResult login(String username, String password, String ip) {
        Account account = accountMapper.findAccountByUsername(username);
        if (account == null || account.getIsDelete() == Constants.True) {
            throw new AppRuntimeException("用户不存在");
        }
        if (account.getIsPublish() == Constants.False) {
            throw new AppRuntimeException("用户已停用");
        }
        if (!PasswordUtil.validatePassword(password, account.getPassword())) {
            throw new AppRuntimeException("密码不正确");
        }
        ApiTokenResult tokenResult = tokenUtil.createToken(String.valueOf(account.getId()));
        AuthLoginResult result = new AuthLoginResult();
        result.setToken(tokenResult.getToken());
        result.setAccountResult(CoreUtil.getDozerMapper().map(account, AccountResult.class));
        return result;
    }

    @Override
    public AuthInfoResult getAuthInfo(Integer accountId) {
        AuthInfoResult authResult = new AuthInfoResult();
        Account account = accountMapper.selectByPrimaryKey(accountId);
        if (account == null || account.getIsDelete() == Constants.True) {
            throw new AppRuntimeException(Constants.kCode_SessionError, "用户不存在");
        }
        if (account.getIsPublish() != Constants.True) {
            throw new AppRuntimeException(Constants.kCode_SessionError, "用户已停用");
        }
        if (account != null) {
            List<ModuleResult> moduleResultList = new ArrayList<>();
            // 全部父菜单
            List<ModuleResult> parentList = moduleMapper.queryModuleNodeList("1");
            Set<Integer> parentSet = new HashSet<>();
            if (CollectionUtils.isNotEmpty(parentList)) {
                moduleResultList.addAll(parentList);
                for (ModuleResult moduleResult : parentList) {
                    parentSet.add(moduleResult.getId());
                }
            }
            //  用户拥有权限的模块列表
            List<ModuleResult> childList = rolePermissionMapper.queryModuleResultListByRoleId(account.getRoleId());
            if (CollectionUtils.isNotEmpty(childList)) {
                for (ModuleResult moduleResult : childList) {
                    if (!parentSet.contains(moduleResult.getId())) {
                        moduleResultList.add(moduleResult);
                    }
                }
            }
            authResult.setModuleResultList(moduleResultList);
            List<String> permissionCodeList = rolePermissionMapper.queryPermissionCodeListByRoleId(account.getRoleId());
            authResult.setPermissionSet(new HashSet<>(permissionCodeList));
        }
        return authResult;
    }

    @Override
    public FormListResult queryAccountPageList(PageListIO io) {
        PageHelper.startPage(io.currentPage(), io.pageSize());
        Page page = (Page<AccountResult>) accountMapper.queryAccountList(io.buildSQLMap());
        return new FormListResult<AccountResult>(page);
    }

    @Override
    public AccountResult findAccountResultById(Integer id) {
        return BeanUtil.cast(accountMapper.selectByPrimaryKey(id), AccountResult.class);
    }

    @Override
    public void saveAccount(AccountDetailIO io) {
        if (!StringUtils.equals(io.getNewPassword(), io.getConfirmPassword())) {
            throw new AppRuntimeException("新密码或确认密码必须相同");
        }
        Account dbEntity = accountMapper.findAccountByUsername(io.getUsername());
        if (dbEntity != null && dbEntity.getIsDelete() != Constants.True) {
            throw new AppRuntimeException("用户已存在");
        }
        Account entity = new Account();
        entity.setIsPublish(io.getIsPublish());
        entity.setIsDelete(Constants.False);
        entity.setRealname(io.getRealname());
        entity.setUsername(io.getUsername());
        entity.setPassword(PasswordUtil.createHash(io.getNewPassword()));
        entity.setEmail(io.getEmail());
        entity.setPoint(io.getPoint());
        entity.setTotalPoint(io.getPoint());
        entity.setRoleId(io.getRoleId());
        entity.setMobile(io.getMobile());
        entity.setTelephone(io.getTelephone());
        entity.setAddress(io.getAddress());
        entity.setDuty(io.getDuty());
        entity.setOrganizationId(io.getOrganizationId());
        entity.setOrderNum(io.getOrderNum());
        accountMapper.insert(entity);
    }

    @Override
    public void updateAccount(AccountDetailIO io) {
        if (StringUtils.isNotBlank(io.getNewPassword()) && StringUtils.isNotBlank(io.getConfirmPassword())
                && !StringUtils.equals(io.getNewPassword(), io.getConfirmPassword())) {
            throw new AppRuntimeException("新密码或确认密码必须相同");
        }
        Account dbEntity = accountMapper.selectByPrimaryKey(io.getId());
        if (dbEntity == null || dbEntity.getIsDelete() == Constants.True) {
            throw new AppRuntimeException("用户不存在");
        }
        dbEntity.setIsPublish(io.getIsPublish());
        dbEntity.setRealname(io.getRealname());
        dbEntity.setUsername(io.getUsername());
        if (StringUtils.isNotBlank(io.getNewPassword())) {
            dbEntity.setPassword(PasswordUtil.createHash(io.getNewPassword()));
        }
        dbEntity.setEmail(io.getEmail());
        dbEntity.setPoint(io.getPoint());
        dbEntity.setTotalPoint(io.getPoint());
        dbEntity.setRoleId(io.getRoleId());
        dbEntity.setMobile(io.getMobile());
        dbEntity.setTelephone(io.getTelephone());
        dbEntity.setAddress(io.getAddress());
        dbEntity.setDuty(io.getDuty());
        dbEntity.setOrganizationId(io.getOrganizationId());
        dbEntity.setOrderNum(io.getOrderNum());
        dbEntity.setUpdateTime(new Date());
        dbEntity.setRemark(io.getRemark());
        accountMapper.updateByPrimaryKeySelective(dbEntity);
    }

    @Override
    public void deleteAccountListByIdList(List<Integer> idList) {
        accountMapper.deleteAccountListByIdList(idList);
    }

    @Override
    public List<RoleResult> queryRoleActiveList() {
        return roleMapper.queryRoleActiveList();
    }

    @Override
    public FormListResult queryRolePageList(PageListIO io) {
        PageHelper.startPage(io.currentPage(), io.pageSize());
        Page page = (Page<RoleResult>) roleMapper.queryRoleList(io.buildSQLMap());
        return new FormListResult<RoleResult>(page);
    }

    @Override
    public RoleResult findRoleResultById(Integer id) {
        RoleResult result = BeanUtil.cast(roleMapper.selectByPrimaryKey(id), RoleResult.class);
        if (result != null) {
            List<Integer> permissionIdList = roleMapper.queryPermissionIdListByRoleId(result.getId());
            result.setPermissionList(permissionIdList);
        }
        return result;
    }

    @Override
    public void saveRole(ApiTokenResult authToken, RoleDetailIO io) {
        Role dbEntity = roleMapper.findRoleByRolename(io.getRoleName());
        if (dbEntity != null && dbEntity.getIsDelete() != Constants.True) {
            throw new AppRuntimeException("角色已存在");
        }
        Role entity = new Role();
        entity.setIsPublish(io.getIsPublish());
        entity.setOrderNum(io.getOrderNum());
        entity.setRoleName(io.getRoleName());
        entity.setIsDefault(io.getIsDefault());
        entity.setCreateAccountId(Integer.valueOf(authToken.getUserId()));
        roleMapper.insertSelective(entity);
        updateRolePermissionList(entity.getId(), io.getPermissionList());
    }

    @Override
    public void updateRole(ApiTokenResult authToken, RoleDetailIO io) {
        Role dbEntity = roleMapper.findRoleByRolename(io.getRoleName());
        if (dbEntity == null || dbEntity.getIsDelete() == Constants.True) {
            throw new AppRuntimeException("角色不存在");
        }
        dbEntity.setIsPublish(io.getIsPublish());
        dbEntity.setOrderNum(io.getOrderNum());
        dbEntity.setRoleName(io.getRoleName());
        dbEntity.setIsDefault(io.getIsDefault());
        roleMapper.updateByPrimaryKeySelective(dbEntity);
        updateRolePermissionList(dbEntity.getId(), io.getPermissionList());
    }

    @Override
    public void deleteRoleListByIdList(List<Integer> idList) {
        roleMapper.deleteRoleListByIdList(idList);
    }

    @Override
    public RoleModulePermissionResult findRoleModulePermissionResult(ApiTokenResult authToken) {
        List<ModuleResult> moduleResultList = moduleMapper.queryAllActiveModuleNodeList();
        List<PermissionResult> permissionResultList = permissionMapper.queryPermissionResultActivedList();
        RoleModulePermissionResult result = new RoleModulePermissionResult();
        result.setModuleResultList(moduleResultList);
        result.setPermissionResultList(permissionResultList);
        return result;
    }


    private void updateRolePermissionList(Integer roleId, List<Integer> permissionList) {
        rolePermissionMapper.deleteByRoleId(roleId);
        if (permissionList != null) {
            Set<Integer> permissionIdSet = new HashSet<>();
            for (Integer permissionId : permissionList) {
                permissionIdSet.add(permissionId);
            }
            List<RolePermission> rolePermissionList = new ArrayList<>();
            List<Integer> parentIdList = rolePermissionMapper.queryParentPermissionIdList(permissionList);
            for (Integer permissionId : parentIdList) {
                RolePermission rolePermission = new RolePermission();
                rolePermission.setRoleId(roleId);
                rolePermission.setPermissionId(permissionId);
                rolePermissionList.add(rolePermission);
            }
            for (Integer permissionId : permissionIdSet) {
                RolePermission rolePermission = new RolePermission();
                rolePermission.setRoleId(roleId);
                rolePermission.setPermissionId(permissionId);
                rolePermissionList.add(rolePermission);
            }
            if (CollectionUtils.isNotEmpty(rolePermissionList)) {
                rolePermissionMapper.insertList(rolePermissionList);
            }
        }
    }


    @Override
    public FormListResult queryModulePageList(PageListIO io) {
        PageHelper.startPage(io.currentPage(), io.pageSize());
        Page page = (Page<ModuleResult>) moduleMapper.queryModuleList(io.buildSQLMap());
        return new FormListResult<ModuleResult>(page);
    }

    @Override
    public ModuleResult findModuleResultById(Integer id) {
        ModuleResult result = BeanUtil.cast(moduleMapper.selectByPrimaryKey(id), ModuleResult.class);
        if (result != null && result.getModuleParentId() != null) {
            if (result.getModuleParentId() != 0) {
                //  根菜单
                Module parentModule = moduleMapper.selectByPrimaryKey(result.getModuleParentId());
                result.setModuleParentName(parentModule.getModuleName());
            } else {
                result.setModuleParentName("-");
            }
        }
        return result;
    }

    @Override
    public void saveModule(ApiTokenResult authToken, ModuleDetailIO io) {
        Module parentModule = moduleMapper.selectByPrimaryKey(io.getModuleParentId());
        if (parentModule == null) {
            throw new AppRuntimeException("父菜单不能为空");
        }
        Module entity = new Module();
        entity.setIsPublish(io.getIsPublish());
        entity.setModuleName(io.getModuleName());
        entity.setModuleCode(StringUtils.trimToEmpty(io.getModuleCode()).toUpperCase());
        entity.setModuleIcon("");
        entity.setModuleCode(io.getModuleCode());
        entity.setModuleUrl(io.getModuleUrl());
        entity.setModuleParentId(parentModule.getId());
        entity.setModuleLevel(parentModule.getModuleLevel() + 1);
        entity.setOrderNum(io.getOrderNum());
        moduleMapper.insertSelective(entity);
    }

    @Override
    public void updateModule(ApiTokenResult authToken, ModuleDetailIO io) {
        if (io.getId() == null)
            throw new AppRuntimeException("ModuleID不能为空");
        Module parentModule = moduleMapper.selectByPrimaryKey(io.getModuleParentId());
        if (parentModule == null) {
            throw new AppRuntimeException("父菜单不能为空");
        }
        Module entity = moduleMapper.selectByPrimaryKey(io.getId());
        entity.setIsPublish(io.getIsPublish());
        entity.setModuleName(io.getModuleName());
        entity.setModuleCode(StringUtils.trimToEmpty(io.getModuleCode()).toUpperCase());
        entity.setModuleIcon("");
        entity.setModuleCode(io.getModuleCode());
        entity.setModuleUrl(io.getModuleUrl());
        entity.setModuleParentId(parentModule.getId());
        entity.setModuleLevel(parentModule.getModuleLevel() + 1);
        entity.setOrderNum(io.getOrderNum());
        moduleMapper.updateByPrimaryKeySelective(entity);
    }

    @Override
    public void deleteModuleListByIdList(List<Integer> idList) {
        moduleMapper.deleteModuleListByIdList(idList);
    }

    @Override
    public List<ModuleResult> queryModuleNodeList(String parentId) {
        return moduleMapper.queryModuleNodeList(parentId);
    }

    @Override
    public int countChildrenModuleListByIdList(List<Integer> idList) {
        return moduleMapper.countChildrenModuleListByIdList(idList);
    }


    @Override
    public FormListResult queryPermissionPageList(PageListIO io) {
        PageHelper.startPage(io.currentPage(), io.pageSize());
        Page page = (Page<PermissionResult>) permissionMapper.queryPermissionList(io.buildSQLMap());
        return new FormListResult<PermissionResult>(page);
    }

    @Override
    public PermissionResult findPermissionResultById(Integer id) {
        PermissionResult result = BeanUtil.cast(permissionMapper.selectByPrimaryKey(id), PermissionResult.class);
        Module module = moduleMapper.selectByPrimaryKey(result.getModuleId());
        result.setModuleName(module.getModuleName());
        return result;
    }

    @Override
    public void savePermission(ApiTokenResult authToken, PermissionDetailIO io) {
        Module module = moduleMapper.selectByPrimaryKey(io.getModuleId());
        String[] codes = StringUtils.splitByWholeSeparatorPreserveAllTokens(io.getPermissionCode(), ",");
        String[] names = StringUtils.splitByWholeSeparatorPreserveAllTokens(io.getPermissionName(), ",");
        for (int i = 0; i < codes.length; i++) {
            String code = StringUtils.upperCase(module.getModuleCode()) + ":" + StringUtils.trimToEmpty(codes[i]).toUpperCase();
            String name = (names.length > i ? names[i] : "-");
            Permission dbEntity = permissionMapper.findPermissionByCodeAndModuleId(io.getModuleId(), code);
            if (dbEntity != null && dbEntity.getIsDelete() != Constants.True) {
                throw new AppRuntimeException("权限码 " + code + " 已存在");
            }
            Permission entity = new Permission();
            entity.setIsPublish(io.getIsPublish());
            entity.setModuleId(io.getModuleId());
            entity.setPermissionName(StringUtils.trimToEmpty(name));
            entity.setPermissionCode(code);
            permissionMapper.insertSelective(entity);
        }
    }

    @Override
    public void updatePermission(ApiTokenResult authToken, PermissionDetailIO io) {
        Permission entity = permissionMapper.selectByPrimaryKey(io.getId());
        entity.setIsPublish(io.getIsPublish());
        entity.setModuleId(io.getModuleId());
        entity.setPermissionName(io.getPermissionName());
        entity.setPermissionCode(StringUtils.upperCase(io.getPermissionCode()).trim());
        permissionMapper.updateByPrimaryKeySelective(entity);
    }

    @Override
    public void deletePermissionListByIdList(List<Integer> idList) {
        permissionMapper.deletePermissionListByIdList(idList);
    }
}
